home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume90
/
examples
/
yafr_1.15
/
YAFR.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-04
|
22KB
|
584 lines
/*- - - - - - - - - - YAFR - Yet Another File Requester - - - - - - - - -*/
/*- - - - - - - - - - - - - - Version 1.15 - - - - - - - - - - - - - - -*/
/*YAFR V1.15 Copyright (c)1989,1990 by Dave Schreiber. All rights reserved.*/
/*YAFR is freely distributable, and may be sold as part of a commercial */
/*program. This copyright message must be included in the documentation */
/*for any program, commercial or otherwise, that uses YAFR. Use of YAFR */
/*in a rogram does not detract in any way from the ownership of YAFR by */
/*its author, Dave Schreiber, nor does it change its status as a freely */
/*distributable program. Dave Schreiber reserves the right to forbid any*/
/*person or company from incorporating YAFR as part of a program owned by*/
/*that person or company. */
/*Compiled under Lattice C V5.04 */
/*Command line: 1> lc -cw -j30 yafr */
/*Generates YAFR.o which is linked into the host program */
/*If you have any comments, suggestions, etc. I can be reached at: */
/*Dave Schreiber */
/*1234 Collins Lane */
/*San Jose, CA 95129-4208 */
/*Usenet: davids@ucscb.ucsc.edu (during the school year) */
/* davids@cup.portal.com (other times) */
#include "yafrHead.h"
/*^^^^system includes, structure definitions, etc.*/
#define CRNT header.current->fib
/*Parameters are: fn-string for filename (33 characters) */
/*dn-string for directory name (150 characters) */
/*en-string for filename extension (.c, .pic, etc. 18 characters) */
/*cn-string for combined directory and filename (183 characters) */
/*(NULL if you don't want the combined filename) */
/*X,Y-YAFR's window's X,Y location (relative to the screen */
/*wn-text for YAFR's window's title bar */
/*scr-Pointer to screen that window should appear on (NULL for */
/*Workbench) filepen-Pen color that filenames should be displayed in */
/*dirpen-Pen color that directory names should be displayed in */
/*DisableInfo-Boolean; TRUE-files ending in .info aren't displayed */
/* FALSE-.info files are displayed */
/*Note! IntuitionBase, GfxBase, and DOSBase must be opened by the */
/*calling program before YAFR is called. DOSBase is usually opened by */
/*the C startup code, but the other aren't. If they aren't, YAFR will */
/*crash! Be warned. */
/*Version 1.1, completed October 30, 1989*/
/*Directory and filename string gadgets now auto-activate and appropriate*/
/*times. A bug that caused an incorrect filename to be returned when the*/
/*user pressed CANCEL has been fixed */
/*Version 1.15 completed January 23, 1990*/
/*A bug that could cause the name of a directory to run outside the */
/*filename box has been eliminated. Also, device names are now converted*/
/*into volume names when selected from the device name buttons on the */
/*right (ex. on my system, when DH2: is pressed, Data: is the name that */
/*appears in the directory box. The source code has had many more */
/*comments added to it and there are new distribution requirements. */
/*Thanks to Bruce Rogers for his FindRoot program which has been */
/*incorporated in YAFR. */
/*-----------------------------------------------------------------------*/
/*Main function. This is what is called by the host program:*/
GetFilename(fn,dn,en,cn,X,Y,wn,scr,filepen,dirpen,DisableInfo)
char *fn,*dn,*en,*cn,*wn; /*See above for parameter definitions*/
USHORT X,Y,filepen,dirpen;
BYTE DisableInfo;
struct Screen *scr;
{
int status=GN_NEWDIR;
struct FileLock *DirLock;
if(DisableInfo)
Info.Flags|=SELECTED;
else
Info.Flags=GADGHIMAGE|GADGIMAGE;
yafr_e_FilenamePenColor = filepen;
yafr_e_DirnamePenColor = dirpen;
DirLock=(struct FileLock *)Lock(dn,ACCESS_READ);
/*Get lock on first directory*/
strcpy(DirNameSIBuff,dn); /*Copy some parameters to this modules*/
strcpy(ExtNameSIBuff,en); /*variables*/
strcpy(filenameSIBuff,fn);
NewFNWindow.LeftEdge=X;
NewFNWindow.TopEdge=Y;
NewFNWindow.Title=(char *)wn;
NewFNWindow.Screen=(struct Screen *) scr;
/*If there's a screen, open on it. Workbench screen otherwise*/
NewFNWindow.Type= (scr) ? CUSTOMSCREEN : WBENCHSCREEN;
/*Open the window*/
if((FNWindow=(struct Window *)OpenWindow(&NewFNWindow))==NULL)
{ /*If it failed...*/
UnLock(DirLock); /*Unlock the directory*/
return(FALSE); /*and return*/
}
/*Write some important text into the title bar: */
SetWindowTitles(FNWindow,-1,"YAFR V1.15 (c)1989 by Dave Schreiber");
SetAPen(FNWindow->RPort,1);
Move(FNWindow->RPort,6,19);
Text(FNWindow->RPort,"Directory",9);
Move(FNWindow->RPort,6,154);
Text(FNWindow->RPort,"Extension",9);
Move(FNWindow->RPort,6,165);
Text(FNWindow->RPort,"Filename",8);
/*Activate the directory string gadget, for user's convenience*/
/*Note! Window must be active for ActivateGadget to work on a*/
/*string window! Take this into account in writing your own code.*/
/*I had to learn the hard way...:-( */
ActivateGadget(&DirName,FNWindow,NULL);
/*Main loop: While requests for reading a new directory keep coming in...*/
while((status = GetName(DirLock)) == GN_NEWDIR)
{ /*keep doing it...*/
UnLock(DirLock); /*Transfer lock to new directory*/
RefreshGadget(&DirName,FNWindow,NULL);
DirLock=(struct FileLock *)Lock(DirNameSIBuff,ACCESS_READ);
ActivateGadget(&filename,FNWindow,NULL); /*Activate filename gadget*/
} /*Loop back, read the new directory, and wait for input again*/
UnLock(DirLock); /*Or we could be finished*/
if(status) /*If OK pressed...*/
{
strcpy(fn,filenameSIBuff); /*Setup the return parameters*/
strcpy(dn,DirNameSIBuff);
strcpy(en,ExtNameSIBuff);
if(cn) /*If cn isn't NULL, there's space for a string, so...*/
{ /*construct the full filename for the host*/
strcpy(cn,DirNameSIBuff);
if( (dn[strlen(dn)-1] != ':') && strlen(dn) )
strcat(cn,"/");
strcat(cn,filenameSIBuff);
}
}
CloseWindow(FNWindow); /*Close the window*/
return(status); /*and return*/
}
GetName(Lock) /*Gets filenames in the directory associated with the*/
struct FileLock *Lock; /*lock, and also gets user input*/
{
struct fibHeader header;
int status3,status2,status;
USHORT FNNumber=0;
header.first=header.directory=NULL;
if(GetFib(&header)==FALSE)
return(FALSE);
SliderSInfo.VertPot=0;
UpdateSlider(1,&SliderSInfo,&Slider);
ClearFileBox();
if(!ispipedevice(DirNameSIBuff)) /*Check for pipe: device*/
if(Lock!=NULL) /*If the lock (& the directory) exist...*/
{
Examine(Lock,&(CRNT)); /*Get the first entry*/
if(GetFib(&header)==FALSE) /*Get next node*/
return(NULL);
while((status3=ExNext(Lock,&(CRNT)))) /*Loop while there are files*/
{
if((status2=((CheckExt(CRNT.fib_FileName,ExtNameSIBuff) ||
CRNT.fib_DirEntryType > 0) && /*If the specified extension*/
CheckInfo(CRNT.fib_FileName)) )) /*(if any) matches and*/
{ /*it isn't a .info file (if masked)*/
if(FNNumber<10) /*display it...*/
PrintFileName(&(CRNT),Rp,XBorder,YBorder+(10*FNNumber++));
else /*or update the slider (if the filename box is full)*/
UpdateSlider(++FNNumber,&SliderSInfo,&Slider);
}
while((status=CheckIntuiMessages(FNNumber,&header))!=GN_DONE)
{ /*After getting a name, checked for IDCMP messages*/
if(status==GN_PARENT) /*If PARENT was pressed*/
{
Parentize(DirNameSIBuff); /*Setup the parent dir*/
RefreshGadget(&DirName,FNWindow,NULL);
FreeFuncMemory(header.directory); /*Free the filename*/
return(GN_NEWDIR); /*list and return*/
}
if(status < GN_PARENT)
{
FreeFuncMemory(header.directory);
return(status); /*For OK,NEWDIR, & CANCEL*/
}
}
if(status2) /*If the filename was valid, append another Fib*/
if(GetFib(&header)==FALSE) /*structure for the next filename*/
return(NULL);
/*If not valid, let the next filename info overwrite the current*/
/*Fib*/
}
header.current->prev->next=NULL; /*Delete the last (unused) Fib*/
if(header.directory->next == header.current) /*If no files*/
header.directory->next=header.first=header.last=
header.top=NULL; /*NULL certain pointers*/
FreeMem(header.current,sizeof(struct fibNode));
}
for(;;) /*Loop until the users says 'Change something!'*/
{
Wait(1<<FNWindow->UserPort->mp_SigBit);
while((status=CheckIntuiMessages(FNNumber,&header))!=GN_DONE)
{
if(status==GN_PARENT) /*PARENT pushed*/
if(Parentize(DirNameSIBuff))
{
RefreshGadget(&DirName,FNWindow,NULL);
FreeFuncMemory(header.directory);
return(GN_NEWDIR);
}
if(status < GN_PARENT) /*Something else pushed*/
{
FreeFuncMemory(header.directory);
return(status); /*For OK,NEWDIR, & CANCEL*/
}
}
}
}
CheckInfo(name) /*Check to see if .info's should be printed*/
char *name;
{
if(!(Info.Flags & SELECTED))
return(TRUE);
return(!(strcmp(&name[strlen(name)-5],".info")==0));
}
ClearFileBox() /*Clear the box with the filenames in it*/
{
SetAPen(Rp,0);
RectFill(Rp,XBorder,YBorder-6,(25*8)+XBorder,YBorder+(100)-4);
SetAPen(Rp,1);
}
Parentize(str) /*Convert a directory identifier string into the one*/
char *str; /*for its parent directory*/
{
int c;
if(str[strlen(str)-1]==':') /*If ':' is the last character*/
return(FALSE); /*We're at the root, and cannot back up*/
for(c=strlen(str)-1;c >= 0;c--)
if(str[c]=='/') /*Delete last '/' & everything after that*/
{
str[c]=NULL;
c=0;
}
else
if(str[c]==':') /*Or delete everything after the ':'*/
{ /*(which leaves the root)*/
str[c+1]=NULL;
c=0;
}
return(TRUE);
}
UpdateSlider(Amt,Info,Gadgt) /*Update the slider bar to reflect*/
USHORT Amt; /*the number of file/dir names available for selection*/
struct PropInfo *Info;
struct Gadget *Gadgt;
{
Info->VertBody=((0xFFFF*10)/Amt);
RefreshGadgets(Gadgt,FNWindow,NULL);
}
CheckIntuiMessages(Max,header) /*Check and respond to the window's IDCMP*/
USHORT Max; /*messages*/
struct fibHeader *header;
{
struct fibNode *cur;
UBYTE c,line;
struct IntuiMessage *mesg;
struct Gadget *InUse;
ULONG Class;
USHORT Code;
SHORT X,Y;
/*Assumes that the calling function has either Wait()ed or wants to*/
/*handle any IDCMP messages that have piled up*/
while((mesg=(struct IntuiMessage *)GetMsg(FNWindow->UserPort))!=NULL)
{
InUse=(struct Gadget *)mesg->IAddress;
X=mesg->MouseX;
Y=mesg->MouseY;
Class=mesg->Class;
Code=mesg->Code;
ReplyMsg(mesg); /*Reply to the message*/
switch(Class) /*Decide what happened*/
{
case MOUSEMOVE: /*If the mouse moved, then the silder is down, so*/
if(Max > 10) /*update the filenames in the box to reflect the*/
UpdateList(SliderSInfo.VertPot,Max,header); /*slider's*/
break; /*position*/
case GADGETUP:
if(InUse->GadgetID <= 10)
{ /*One of the device gadgets was pushed*/
if(!ispipedevice(InUse->GadgetText->IText))
{ /*Find the volume name if it isn't the PIPE:*/
MakeAbsName(InUse->GadgetText->IText);
strcpy(DirNameSIBuff,absDirName);
strcat(DirNameSIBuff,":");
}
else
strcpy(DirNameSIBuff,InUse->GadgetText->IText);
RefreshGadget(&DirName,FNWindow,NULL);
return(GN_NEWDIR);
}
switch(InUse->GadgetID)
{
case 14: /*CANCEL was pushed*/
return(GN_CANCEL);
case 12:
case 13: /*OK was pushed or return was pressed in the*/
return(GN_OK); /*filename's box*/
case 15:
return(GN_PARENT); /*PARENT was pushed*/
case 11: /*Return was pushed while the extension or dirname*/
case 18: /*box was active, so reread the old directory or read*/
return(GN_NEWDIR); /*a new one*/
}
return(GN_RIEN); /*Nothing important*/
break;
case GADGETDOWN: /*The .info gadget was pressed?*/
if(InUse->GadgetID == 18)
return(GN_NEWDIR);
/*A file/dir name in the box was clicked on*/
if(!ispipedevice(DirNameSIBuff)) /*If the pipe:*/
{ /*don't try & get a filename*/
line=(Y-YBorder+7)/10; /*Get line clicked on*/
for(c=0,cur=(struct fibNode *)header->top;c!=line && cur!=NULL;c++)
cur=(struct fibNode *)cur->next; /*Find the file's Fib*/
if(cur != NULL) /*If the file exists*/
if(cur->fib.fib_DirEntryType > 0)
{ /*It's a directory, so read that directory*/
if(DirNameSIBuff[strlen(DirNameSIBuff)-1] != ':')
strcat(DirNameSIBuff,"/");
strcat(DirNameSIBuff,cur->fib.fib_FileName);
RefreshGadget(&DirName,FNWindow,NULL);
return(GN_NEWDIR);
}
else /*otherwise, return the filename clicked upon*/
{
strcpy(filenameSIBuff,cur->fib.fib_FileName);
RefreshGadget(&filename,FNWindow,NULL);
}
}
}
}
return(GN_DONE); /*All done...*/
}
UpdateList(Pos,Num,header) /*Update filenames in the filename box*/
USHORT Pos; /*According to the slider's position*/
USHORT Num;
struct fibHeader *header;
{
static USHORT LastFirstItem=30000;
ULONG FirstItem;
FirstItem=(((Pos+1)*(Num-10)) >> 16);
if( FirstItem != LastFirstItem)
RewriteList(FirstItem,header);
LastFirstItem=FirstItem;
}
RewriteList(First,header) /*Rewrite the list of filenames in the*/
USHORT First; /*filename box...*/
struct fibHeader *header;
{
register struct fibNode *node;
register USHORT c,Y;
if(First) /*If we're not starting at the start...*/
for(c=0,node=(struct fibNode *)header->first;c < First;c++)
node=(struct fibNode *)node->next; /*Get the first filename*/
else /*Otherwise, start at the top*/
node=(struct fibNode *)header->first;
header->top=(struct fibNode *)node;
/*Print the filenames (up to 10)*/
for(c=0,Y=YBorder;(c < 10) && (node!=NULL);
c++,Y+=10,node=(struct fibNode *)node->next)
PrintFileName(&(node->fib),Rp,XBorder,Y);
}
CheckExt(name,ext) /*Check to see if 'name' has the extension '.ext'*/
char *name,*ext;
{
if(strlen(name) >= strlen(ext))
if(strcmp(&name[strlen(name)-strlen(ext)],ext)==0)
return(TRUE);
return(FALSE);
}
GetFib(header)
struct fibHeader *header;
{
header->last=(struct fibNode *)header->current;
if((header->current=(struct fibNode *) /*Allocate a FIB structure*/
AllocMem(sizeof(struct fibNode),MEMF_PUBLIC|MEMF_CLEAR))==NULL)
{
FreeFuncMemory(header->current); /*Whoops, it didn't work...*/
return(FALSE);
}
if(header->directory==NULL) /*Must want it for a directory...*/
header->directory=(struct fibNode *)header->current;
else /*Append to the current FIB list*/
{
if(header->first==NULL)
{
header->directory->next=header->first=header->last=header->top=
(struct fibNode *)header->current;
CopyFIB(&(header->directory->fib),&(header->current->fib));
}
else
{
CopyFIB(&(header->last->fib),&(header->current->fib));
header->last->next=(struct fibNode *)header->current;
header->current->prev=(struct fibNode *)header->last;
}
}
return(TRUE);
}
CopyFIB(from,to) /*Copy a fileinfoblock from 'from' to 'to'*/
struct FileInfoBlock *from,*to;
{
to->fib_DiskKey=from->fib_DiskKey;
to->fib_DirEntryType=from->fib_DirEntryType;
to->fib_Protection=from->fib_Protection;
to->fib_EntryType=from->fib_EntryType;
to->fib_Size=from->fib_Size;
to->fib_NumBlocks=from->fib_NumBlocks;
strcpy(to->fib_FileName,from->fib_FileName);
strcpy(to->fib_Comment,from->fib_Comment);
to->fib_Date.ds_Days=from->fib_Date.ds_Days;
to->fib_Date.ds_Minute=from->fib_Date.ds_Minute;
to->fib_Date.ds_Tick=from->fib_Date.ds_Tick;
return(TRUE);
}
PrintFileName(fib,RPrt,X,Y) /*Print a filename in the filename box*/
struct FileInfoBlock *fib;
struct RPort *RPrt;
USHORT X,Y;
{
UWORD len;
char name[40];
strcpy(name,fib->fib_FileName);
if(fib->fib_DirEntryType > 0) /*Set the pen color, according to whether*/
{ /*we're printing a filename or a directory name*/
SetAPen(RPrt,yafr_e_DirnamePenColor);
strcat(name," (dir)"); /*Append ' (dir)' if it's a directory*/
}
else
SetAPen(RPrt,yafr_e_FilenamePenColor);
Move(RPrt,X,Y);
Text(RPrt," ",25); /*Blank out the space*/
Move(RPrt,X,Y);
len = (strlen(fib->fib_FileName)<=25) ? strlen(fib->fib_FileName) : 25;
Text(RPrt,fib->fib_FileName,len); /*Trundicate the filename at 25 chars*/
/*and print it.*/
}
RefreshGadget(Gadg,Wdw,Req) /*Refresh a specific gadget*/
struct Gadget *Gadg; /*(keeps RefreshGadgets() from refreshing*/
struct Window *Wdw; /*the entire gadget list*/
struct Req *Req;
{
struct Gadget *next;
next=(struct Gadget *)Gadg->NextGadget;
Gadg->NextGadget=NULL;
RefreshGadgets(Gadg,Wdw,Req);
Gadg->NextGadget=(struct Gadget *)next;
return(TRUE);
}
FreeFuncMemory(first) /*Free the memory taken up by a fib list*/
register struct fibNode *first;
{
register struct fibNode *next,*current;
next=(struct fibNode *)first->next;
FreeMem(first,sizeof(struct fibNode));
while((current=(struct fibNode *)next)!=NULL)
{
next=(struct fibNode *)current->next;
FreeMem(current,sizeof(struct fibNode));
}
}
ispipedevice(device) /*Checks to see if the device is the PIPE:*/
char *device;
{
char temp[6];
int c;
for(c=0;c<5;c++) /*Convert weird capitalization (pIPe:) to pipe:*/
temp[c]=tolower(device[c]); /*So as to make it easy to check*/
temp[5]=NULL;
if(strcmp(device,"pipe:")==0)
return(TRUE);
else
return(FALSE);
}
/*!*******************************************************************
* FindRoot by Bruce Rogers 1/20/90
*********************************************************************/
/*!*******************************************************************
* Kludges disk:name/directory with filename so we can just read it.
*********************************************************************/
void DosConcatenate(string1,string2,result)
char string1[],string2[],result[];
{
short i,j;
for(i=0; string1[i] != '\0'; i++)
result[i]=string1[i];
if ((result[i-1] != ':') && (result[i-1] != '/') && (i!=0) && string2[0]!=0)
{
result[i]='/';
++i;
}
for(j=0; string2[j] != '\0'; j++)
result[i+j] = string2[j];
result[i+j] = '\0';
}
/*!*******************************************************************
* Recursively go up parent chain, looking for oldest parent.
* Create the absolute path string as we go.
*********************************************************************/
SeekRoot(oldlock)
ULONG oldlock;
{
short i;
struct FileInfoBlock fileInfo;
ULONG newlock;
Examine(oldlock,&fileInfo);
DosConcatenate(fileInfo.fib_FileName,absDirName,absDir);
for(i=0;i<MAXPATHSTRING;i++) absDirName[i]=absDir[i];
newlock=ParentDir(oldlock);
UnLock(oldlock);
oldlock=newlock;
if (oldlock!=NULL) SeekRoot(oldlock);
}
/*!*******************************************************************
* Given a path, sets absDirName equal to the absolute path
*********************************************************************/
MakeAbsName(dirName)
char *dirName;
{
short i;
ULONG lock;
for(i=0;i<MAXPATHSTRING;i++) absDirName[i]=absDir[i]=0;
lock=Lock(dirName,ACCESS_READ);
if (lock==NULL) return;
SeekRoot(lock);
for(i=0;i<MAXPATHSTRING;i++)
{
if (absDirName[i]=='/')
{
absDirName[i]=':';
break;
}
}
}
/*End of YAFR.c*/